import copy

import matplotlib.pyplot as plt
import numpy as np
import xlwings as xw
from matplotlib.animation import FuncAnimation


class GameOfLife():
    def __init__(self, gridSize,name):
        self.gridSize = gridSize

        self.initplot()
        self.initdata(name)

    def initplot(self):
        self.fig, self.ax = plt.subplots()
        plt.axis('square')
        plt.xticks([])
        plt.yticks([])
        self.ln, = plt.plot([], [], 's', c='k')
        # for i in range(self.gridSize):
        #     self.ax.plot([i, i], [0, -1 * self.gridSize], lw=1, c='k')
        #     self.ax.plot([0, self.gridSize], [-i, -i], lw=1, c='k')
        self.ax.set_xlim([0, self.gridSize])
        self.ax.set_ylim([-1 * self.gridSize, 0])

    def initdata(self, name=''):
        if name == '':
            self.array = np.random.randint(0, 1 + 1, int(self.gridSize * self.gridSize)).reshape(
                (self.gridSize, self.gridSize))
        else:
            app = xw.App(visible=False, add_book=False)
            wb = app.books.open(name, read_only=True)
            xs = wb.sheets[0]
            self.array = np.zeros((self.gridSize, self.gridSize))
            for i in range(self.gridSize):
                for j in range(self.gridSize):
                    if xs[i, j].color == (0, 0, 0):
                        self.array[i, j] = 1
            wb.close()
            app.kill()

    def calculate(self):
        self.lastArray = copy.deepcopy(self.array)
        for i in range(self.gridSize):
            for j in range(self.gridSize):
                countLife = 0
                temp = [[i - 1, j - 1], [i, j - 1], [i + 1, j - 1], [i - 1, j], [i + 1, j],
                        [i - 1, j + 1], [i, j + 1], [i + 1, j + 1]]
                for ii, jj in temp:
                    if ii < 0 or ii >= self.gridSize or jj < 0 or jj >= self.gridSize:
                        pass
                    else:
                        if self.lastArray[ii, jj] == 1:
                            countLife += 1

                if self.lastArray[i, j] == 1:
                    if countLife < 2:  # 任何活细胞如果活令居少于2个，则死掉
                        self.array[i, j] = 0
                    elif countLife == 2 or countLife == 3:  # 任何活细胞如果活邻居为2个或者3个，则继续活
                        pass
                    else:
                        self.array[i, j] = 0  # 任何活细胞如果活令居大于三个，则死掉
                else:
                    if countLife == 3:
                        self.array[i, j] = 1
                    else:
                        pass

    def update(self, n):
        if n != 0:
            self.calculate()
        xlist = []
        ylist = []
        for i in range(self.gridSize):
            for j in range(self.gridSize):
                if self.array[i, j] == 1:
                    xlist.append(j + 0.5)
                    ylist.append(-1 * i - 0.5)
        self.ln.set_data(xlist, ylist)
        plt.xlabel(str(n + 1))

    def run(self):
        animation = FuncAnimation(self.fig, self.update, frames=200, interval=100, repeat=False)
        plt.show()  # 显示图片


if __name__ == '__main__':
    size = 40
    name = '滑翔者.xlsx'
    game = GameOfLife(size,name)
    game.run()
